package com.ouc.common.utils;

import com.ouc.common.utils.file.FileUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.lang.NonNull;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;

/**
 * python调用工具
 *
 * @author B504
 */
@Slf4j
public class ProgramUtil {
  /**
   * 启动cmd窗口
   *
   * @param command 命令行
   * @return 可以被cmd运行的命令行
   * @throws IOException
   */
  public static String executeCmd(String command) throws IOException {
    /**
     * 执行cmd窗口
     */
    Runtime runtime = Runtime.getRuntime();
    Process process = runtime.exec("cmd /c " + command);
    BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream(), "UTF-8"));
    String line = null;
    StringBuilder build = new StringBuilder();
    while ((line = br.readLine()) != null) {
      build.append(line);
    }
    return build.toString();
  }

  /**
   * 获取某个应用的启动状态
   *
   * @param programName 在任务管理器中的名字
   * @return true/false
   * @throws IOException
   */
  @NonNull
  public static boolean checkProgram(@NonNull String programName) throws IOException {
    log.info("检测应用程序：" + programName + "运行状态");
    boolean result = false; //  默认没有启动
    String cmdLines = executeCmd("tasklist |findstr /i \"" + programName + "\"");
    if (StringUtils.isNotEmpty(cmdLines)) {
      log.info("后台任务列表找到" + programName + "程序正在运行");
      result = true;
    } else {
      log.error("没有在后台任务列表找到" + programName);
    }
    return result;
  }

  /**
   * 关闭某个应用，在任务管理器中直接关掉
   *
   * @param programName 任务管理器中应用的名字
   * @throws IOException
   */
  @NonNull
  public static void closeProgram(@NonNull String programName) throws IOException {
    log.info("关闭应用程序：" + programName);
    if (StringUtils.isNotBlank(programName)) {
      executeCmd("taskkill /F /IM " + programName);
    }
  }

  /**
   * 打开某个应用（双击）
   *
   * @param programPath 应用绝对路径
   */
  public static void startProgram(String programPath) {
    try {
      //  如果路径存在空格（只有一个），将空格用双引号引起来再传给cmd
      if (programPath.contains(" ")) {
        programPath = programPath.replaceAll(" ", "\" \"");
      }
      String cmd = "cmd /c  " + programPath;
      Process ps = Runtime.getRuntime().exec(cmd);
      errorMessage(ps);
      infoMessage(ps);
      ps.waitFor();
    } catch (Exception e) {
      e.printStackTrace();
    }

  }

  /**
   * 打开应用程序通过进入相对路径
   *
   * @param programPath 程序绝对路径
   */
  public static void startProgramByRelativePath(String programPath) {
    try {
      String header = "cmd /c ";
      StringBuilder sb = new StringBuilder();
      sb.append(header).append(programPath.charAt(0)).append(":").append(" & ")
          .append("cd ").append(new File(programPath).getParent()).append(" & ")
          .append(FileUtils.getName(programPath));
      Process pro = Runtime.getRuntime().exec(sb.toString());
      ProgramUtil.infoMessage(pro);
    } catch (Exception e) {
      e.printStackTrace();
    }
  }

  /**
   * 查看cmd报错信息，java通过cmd运行命令cmd无法打开
   * 所以使用控制台打印方式打印报错信息
   *
   * @param ps 进程
   */
  public static void errorMessage(Process ps) {
    try {
      BufferedReader input = new BufferedReader(new InputStreamReader(ps.getErrorStream(), "GBK"));
      String line = null;
      while ((line = input.readLine()) != null) {
        log.info(line);
      }
      int exitVal = ps.waitFor();
      log.info("Exited with error code" + exitVal);

    } catch (Exception e) {
      e.printStackTrace();
    }

  }

  /**
   * 打印cmd详细信息
   *
   * @param ps 进程
   */
  public static void infoMessage(Process ps) {
    try {
      BufferedReader input = new BufferedReader(new InputStreamReader(ps.getInputStream(), "GBK"));
      String line = null;
      while ((line = input.readLine()) != null) {
        log.info(line);
      }
      int exitVal = ps.waitFor();
      log.info("Exited with info code" + exitVal);

    } catch (Exception e) {
      e.printStackTrace();
    }

  }

}
